package net.mingsoft.expertmanage.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

/**
 * Excel工具类
 */
public class ExcelUtil {

    /**
     * 导出Excel
     * @param response 响应
     * @param data 数据列表
     * @param fileName 文件名
     * @param sheetName sheet名称
     * @param clazz 实体类
     * @param <T> 泛型
     * @throws IOException IO异常
     */
    public static <T> void exportExcel(HttpServletResponse response, List<T> data, String fileName, String sheetName, Class<T> clazz) throws IOException {
        // 表头样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        
        // 内容样式
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            
            // 这里URLEncoder.encode可以防止中文乱码
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
            
            EasyExcel.write(response.getOutputStream(), clazz)
                    .registerWriteHandler(horizontalCellStyleStrategy)
                    .sheet(sheetName)
                    .doWrite(data);
            
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("导出Excel失败", e);
        }
    }
    
    /**
     * 导出多个Sheet的Excel
     * @param response 响应
     * @param fileName 文件名
     * @param sheetDataList 多个sheet的数据列表
     * @throws IOException IO异常
     */
    public static void exportExcelWithMultipleSheets(HttpServletResponse response, String fileName, List<SheetData<?>> sheetDataList) throws IOException {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");
            
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
            
            for (int i = 0; i < sheetDataList.size(); i++) {
                SheetData<?> sheetData = sheetDataList.get(i);
                WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetData.getSheetName())
                        .head(sheetData.getClazz())
                        .build();
                
                excelWriter.write(sheetData.getData(), writeSheet);
            }
            
            excelWriter.finish();
            
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("导出Excel失败", e);
        }
    }
    
    /**
     * Sheet数据
     * @param <T> 泛型
     */
    public static class SheetData<T> {
        private String sheetName;
        private List<T> data;
        private Class<T> clazz;
        
        public SheetData(String sheetName, List<T> data, Class<T> clazz) {
            this.sheetName = sheetName;
            this.data = data;
            this.clazz = clazz;
        }
        
        public String getSheetName() {
            return sheetName;
        }
        
        public List<T> getData() {
            return data;
        }
        
        public Class<T> getClazz() {
            return clazz;
        }
    }
} 